﻿//Basic Linq to Sql abstract repository to be inherited and used for the generic controller
//Developed by Matthew Hood - 2009

using System;
using System.Data.Linq;
using System.Linq;
using System.Linq.Dynamic;

namespace Softwarehouse.MvcCrud.Repository
{
    public abstract class LinqToSqlRepository<TKeyType, TModel> : IMvcCrudRepository<TKeyType, TModel> where TModel : class, new() where TKeyType : IComparable
    {
        public DataContext db;
        public string primaryKey { get; set; }
        public string orderBy { get; set; }

        protected LinqToSqlRepository(DataContext db, string primaryKey, string orderBy)
        {
            this.db = db;
            this.primaryKey = primaryKey;
            this.orderBy = orderBy;
        }

        public virtual IQueryable<TModel> All()
        {
            return db.GetTable<TModel>();
        }

        public virtual IQueryable<TModel> AllOrdered()
        {
            return All().OrderBy(orderBy);
        }

        public virtual TModel Single(TKeyType id)
        {
            //TODO: change to something along the lines of Single(t => PrimaryKey(t) == id), and avoid dynamic linq
            return db.GetTable<TModel>().Where( primaryKey +  " = @0", id).First();
        }

        public virtual void Create(TModel t)
        {
            db.GetTable<TModel>().InsertOnSubmit(t);
            db.SubmitChanges();
        }

        private TKeyType PrimaryKey(TModel t)
        {
            return (TKeyType)t.GetType().GetProperty(primaryKey).GetValue(t, null);
        }

        public virtual void Save(TModel t)
        {
            TModel old = Single(PrimaryKey(t));
            DataContext secondContextToAttach = new DataContext(db.Connection);
            secondContextToAttach.GetTable<TModel>().Attach(t, old);
            secondContextToAttach.SubmitChanges();
        }

        public virtual void Delete(TKeyType id)
        {
            db.GetTable<TModel>().DeleteOnSubmit(Single(id));
            db.SubmitChanges();
        }
    }
}